let string = Object.prototype.toString;
//<-------判断类函数Start
// 判断数据类型
export function GJ_isType(val) {
    let type = string.call(val);
    return type.slice(8, -1);
}
// 判断是不是对象
export function GJ_isObject(val) {
    return val instanceof Object;
}
// 判断是不是数组
export function GJ_isArray(val) {
    return val instanceof Array;
}
// 判断俩个值是否相等 数据类型/结构
export function GJ_isEqual(val1, val2) {
    let v1 = GJ_isType(val1);
    let v2 = GJ_isType(val2);
    if (v1 === v2) {
        //    判断是不是数组
        if (GJ_isArray(val1)) {
            // 判断数组长度是否相等
            if (val1.length === val2.length) {
                let result = val1.every((item, index) => {
                    return item === val2[index];
                });
                return result;
            } else {
                return false;
            }
        } else if (GJ_isObject(val1)) {
            let num1 = Object.keys(val1);
            let num2 = Object.keys(val2);
            if (num1.length === num2.length) {
                let result = num1.every((item) => {
                    return GJ_isEqual(val1[item], val2[item]);
                });
                return result;
            } else {
                return false;
            }
        } else {
            return val1 === val2;
        }
    } else {
        return false;
    }
}
// 判断是不是promise
export function GJ_isPromise(val) {
    return GJ_isType(val) === "Promise";
}
//判断是否是原生函数
export function GJ_isNative(fn) {
    let result = fn.toString();
    let reg = /native/;
    return reg.test(result);
}
//判断某个属性是否是对象的属性
export function GJ_isProperty(property, obj) {
    return property in obj;
}
//判断是否为null或者undefined 是返回false
export function GJ_isNorU(item) {
    if (item == null || item == undefined) {
        return false;
    } else {
        return true;
    }
}
//<------判断类函数End>

// <-------工具类函数Start
// 缓存函数 -- 相同函数参数直接在缓存中取值
export function GJ_cache(fn) {
    let cache = Object.create({});
    return function (...args) {
        let key = JSON.stringify(args);
        return cache[key] || (cache[key] = fn.apply(fn, args));
    };
}
// 节流函数 -- 一定时间内多次触发只执行第一次
export function GJ_throttle(fn, time) {
    let timer = null;
    return function (...args) {
        if (!timer) {
            timer = setTimeout(() => {
                clearTimeout(timer);
                timer = null;
                fn.apply(fn, args);
            }, time);
        }
    };
}
// 防抖函数 -- 一定时间内多次触发只执行最后一次
export function GJ_shake(fn, time) {
    let timer = null;
    return function (...args) {
        if (!timer) {
            timer = setTimeout(() => {
                clearTimeout(timer);
                timer = null;
                fn.apply(args);
            }, time);
        }
    };
}
//添加函数 -- 将小于等于9的数值添加0前缀
export function GJ_addStr(str) {
    if (str <= 9) {
        return "0" + str;
    } else {
        return str;
    }
}
// 当前时间函数 -- 根据type返回具体的时间 type:  date-time date time year mon day h m s
export function GJ_nowTime(type = "date-time", line = "/") {
    let date = new Date();
    let year = date.getFullYear();
    let mon = date.getMonth() + 1;
    let day = date.getDate();
    let hou = date.getHours();
    let min = date.getMinutes();
    let sec = date.getSeconds();
    switch (type) {
        case "date-time":
            return `${year}${line}${GJ_addStr(mon)}${line}${GJ_addStr(
                day
            )} ${GJ_addStr(hou)}:${GJ_addStr(min)}:${GJ_addStr(sec)}`;
        case "date":
            return `${year}${line}${GJ_addStr(mon)}${line}${GJ_addStr(day)}`;
        case "time":
            return `${GJ_addStr(hou)}:${GJ_addStr(min)}:${GJ_addStr(sec)}`;
        case "year":
            return `${year}`;
        case "mon":
            return `${GJ_addStr(mon)}`;
        case "day":
            return `${GJ_addStr(day)}`;
        case "h":
            return `${GJ_addStr(hou)}`;
        case "m":
            return `${GJ_addStr(min)}`;
        case "s":
            return `${GJ_addStr(sec)}`;
        default:
            return "参数不正确";
    }
}
// 将时间戳转化成具体时间 -- 相互转化 reg:true时间戳 false:具体时间
export function GJ_timestamp(stamp, reg) {
    if (reg) {
        return new Date(stamp).getTime();
    } else {
        return GJ_nowTime(stamp);
    }
}
//深复制函数 -- 深复制一个对象、新的内存地址
export function GJ_deepClone(obj) {
    return JSON.parse(JSON.stringify(obj));
}
//复制指定内容函数doc:需要复制的文本 返回true或false
export function GJ_copy(doc) {
    let input = document.createElement("input");
    document.body.appendChild(input);
    input.setAttribute("value", doc);
    input.select();
    if (document.execCommand("copy")) {
        document.execCommand("copy");
        document.body.removeChild(input);
        return true;
    } else {
        document.body.removeChild(input);
        return false;
    }
}
//过滤函数 传入数据及指定的过滤条件 返回符合条件的数据
export function GJ_filter(initData, reg) {
    if (GJ_isArray(initData)) {
        let list = initData.filter((item) => {
            return new RegExp(reg).test(item.insertTime);
        });
        return list;
    } else {
        return `你需要传一个数组作为原参数、但你传的是${GJ_isType(initData)}`;
    }
}
//数组去重
export function GJ_repeat(arr) {
    let result = GJ_isArray(arr);
    if (result) {
        return [...new Set(arr)]
    } else {
        return new Error("GJ_repeat数组去重函数期望你传的是一个数组");
    }
}
// 合并策略 数组不去重 对象后者覆盖前者
export function GJ_merges(val1, val2) {
    let v1 = GJ_isType(val1);
    let v2 = GJ_isType(val2);
    console.log(v1, v2);
    if (v1 === v2) {
        if (v1 === "Array") {
            //数组合并
            return val1.concat(val2);
        } else if (v1 === "Object") {
            //对象合并 创建一个空对象
            let obj = {}
            // 遍历并合并俩个对象的属性(去重)
            let key1 = Object.keys(val1);
            let key2 = Object.keys(val2);
            let repeat = GJ_repeat([...key1, ...key2]);
            // 遍历属性合并
            repeat.forEach((item) => {
                if (GJ_isProperty(item, val1) && GJ_isProperty(item, val2)) {
                    // 判断是否都存在这个属性 
                    if (GJ_isType(val1[item]) == GJ_isType(val2[item])) {
                        //判断数据类型是否一致(递归)
                        if (GJ_isNorU(val1[item]) && (typeof val1[item] == "object")) {
                            obj[item] = GJ_merges(val1[item], val2[item])
                        } else {
                            obj[item] = val2[item];
                        }
                    } else {
                        //数据类型不一致 后者覆盖前者
                        obj[item] = val2[item];
                    }
                } else if (GJ_isProperty(item, val1)) {
                    // 判断是否只有第一个对象存在这个属性
                    if (GJ_isNorU(val1[item]) && (typeof val1[item] == "object")) {
                        //当属性不为null或undefined且typeof为object时执行深复制
                        obj[item] = GJ_deepClone(val1[item]);
                    } else {
                        //否则直接复制
                        obj[item] = val1[item];
                    }
                } else {
                    // 判断是否只有第二个对象存在这个属性
                    if (GJ_isNorU(val2[item]) && (typeof val2[item] == "object")) {
                        //当属性不为null切typeof为object时执行深复制
                        obj[item] = GJ_deepClone(val2[item]);
                    } else {
                        //否则直接复制
                        obj[item] = val2[item];
                    }
                }
            })
            return obj;
        } else {
            //基础类型合并
            return val1 + val2;
        }
    } else {
        return new Error(`不同数据类型不能合并`);
    }
}

//经纬度转换 度数 <=> 小数 reg=true表示转小数
export function GJ_Nautica(val, reg) {
    if (reg) {
        let arrs = val.split("°");
        let arr1 = arrs[1].split("'");
        let arr2 = arr1[1].split(`.`)
        let arr3 = parseInt(arr2[1]);
        let a = ((`${arr2[0]}.${arr3}` * 1) / 3600).toFixed(6);
        let b = (arr1[0] * 1 / 60).toFixed(6);
        let c = Number(arrs[0]) + Number(a) + Number(b);
        return c
    } else {
        let site = val.site;
        let h = Math.floor(site);
        let val1 = (site - h) * 60;
        let m = Math.floor(val1);
        let s = ((val1 - m) * 60).toFixed(6);
        let result = `${h}°${m}'${s}"`;
        return result;
    }
}

// <-------工具类函数End

// <-------实用类函数Start
// 图片下载 -- 原理利用a标签以及canvas 传入图片路径以及图片名字
export function GJ_imageDownload(url, fileName) {
    let image = new Image();
    image.setAttribute("crossOrigin", "anonymous");
    image.src = url;
    image.onload = () => {
        let canvas = document.createElement("canvas");
        canvas.width = image.width;
        canvas.height = image.height;
        let ctx = canvas.getContext("2d");
        ctx.drawImage(image, 0, 0, image.width, image.height);
        canvas.toBlob((blob) => {
            let url = URL.createObjectURL(blob);
            let eleLink = document.createElement("a");
            eleLink.download = fileName;
            eleLink.href = url;
            eleLink.click();
            eleLink.remove();
            // 用完释放URL对象
            URL.revokeObjectURL(url);
        });
    };
}
//只允许输入数字 info是绑定的字段 item是输入的字符 len是限制的长度(仅对vue有效)
export function GJ_allowNumber(info, item, len) {
    let type = parseInt(item);
    if (type + '' == "NaN") {
        this.form[info] = "";
    } else {
        let lenInfo = this.form[info].length;
        if (len >= lenInfo) {
            this.form[info] = parseInt(item);
        }
    }
}
//返回一个不重复的1个随机数字
export function GJ_randomNum(){
    return Math.floor(Math.random()*10);
}
//返回一个len位随机数字字符串
export function GJ_randomStr(len){
    let str = ""
    for(let i=0;i<len;i++){
        str += GJ_randomNum();
    }
    return str;
}
// <-------实用类函数End

//<------ 常用正则
// 手机号码正则
export let GJ_telReg = /^1[3456789]d{9}$/;
//邮箱正则
export let GJ_emailReg = /^\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/;